package a.client;/**
 * Description: 使用需要修改服务器地址
 * Param:
 * return:
 * Author:20201002983郑雨蓓
 * Date: 2022/9/13
 */

import a.server.ConnectionProvider;
import a.server.Register;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Pair;

import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

public class ChatFX extends Application {

  public static void main(String[] args) {
    launch(args);
  }

  private Button btnConnect = new Button("连接");
  private Button btnExit = new Button("退出");
  private Button btnSend = new Button("发送");
  //在这里修改服务器地址
  private String ip = "192.168.178.72";
  private String port = "8008";
  private TextField tfChatMember = new TextField("默认群聊");
  private TextField tfSend = new TextField("Hello");
  private TextArea taDisplay = new TextArea();//显示信息的文本区域
  private ChatClient chatClient;
  private Register register;
  Thread receiveThread; //定义成员变量，读取服务器信息的线程

  public void start(Stage primaryStage) {

    //上边框加入
    HBox upBox = new HBox();
    upBox.setSpacing(10);//设置内边距
    upBox.setPadding(new Insets(10, 30, 10, 30));//设置外边距
    upBox.setAlignment(Pos.CENTER);
    upBox.getChildren().addAll(new Label("输入私聊成员名字:"), tfChatMember, btnConnect);
    //内容显示区域
    VBox vBox = new VBox();
    vBox.setSpacing(10);//各控件之间的间隔
    vBox.setPadding(new Insets(10, 20, 10, 20));
    vBox.getChildren().addAll(new Label("信息显示区："),
      taDisplay, new Label("信息输入区："), tfSend);
    VBox.setVgrow(taDisplay, Priority.ALWAYS);//设置显示信息区的文本区域可以纵向自动扩充范围

    //不可编辑,自动换行
    taDisplay.setEditable(false);
    taDisplay.setWrapText(true);
    tfSend.setEditable(false);
    tfChatMember.setEditable(false);
    btnSend.setDisable(true);

    //鼠标移动事件复制文件名
    taDisplay.selectionProperty().addListener((observable, oldValue, newValue) -> {
      //只有当鼠标拖动选中了文字才复制内容
      if (!taDisplay.getSelectedText().equals(""))
        tfSend.setText(taDisplay.getSelectedText());
    });

    //底部按钮区域
    HBox hBox = new HBox();
    hBox.setSpacing(10);
    hBox.setPadding(new Insets(10, 20, 10, 20));
    hBox.setAlignment(Pos.CENTER_RIGHT);
    hBox.getChildren().addAll(btnSend, btnExit);

    BorderPane mainPane = new BorderPane();
    mainPane.setTop(upBox);
    mainPane.setCenter(vBox);
    mainPane.setBottom(hBox);
    Scene scene = new Scene(mainPane, 700, 400);
    primaryStage.setTitle("网络聊天室");
    primaryStage.setScene(scene);
    primaryStage.show();

//--------注册登录对话框------------------

    Dialog<Pair<String, String>> dialog = new Dialog<>();
    dialog.setTitle("注册登录");
    dialog.setHeaderText(null);

    ButtonType btLogin = new ButtonType("登录");
    ButtonType btRegister = new ButtonType("注册");
    ButtonType btCancel = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
    dialog.getDialogPane().getButtonTypes().addAll(btRegister, btLogin, btCancel);
    TextField tfUsername = new TextField();
    tfUsername.setPromptText("Username");
    tfUsername.setText("bibi");
    PasswordField tfPassword = new PasswordField();
    tfPassword.setPromptText("Password");
    tfPassword.setText("20201002983");

    GridPane grid = new GridPane();
    grid.setHgap(10);
    grid.setVgap(10);
    grid.setPadding(new Insets(20, 150, 10, 10));
    grid.add(new Label("Username:"), 0, 0);
    grid.add(tfUsername, 1, 0);
    grid.add(new Label("Password:"), 0, 1);
    grid.add(tfPassword, 1, 1);
    dialog.getDialogPane().setContent(grid);

    dialog.setResultConverter(dialogButton -> {
      register = new Register(new ConnectionProvider());
      String username = tfUsername.getText().trim();
      String password = tfPassword.getText().trim();
      if (dialogButton.equals(btLogin)) {
        boolean res = register.login(username, password);
        if (!res) {
          Alert alert = new Alert(Alert.AlertType.WARNING);
          alert.setTitle(null);
          alert.setHeaderText(null);
          alert.setContentText("登陆失败!");
          alert.showAndWait();
        } else {
          return new Pair<>(tfUsername.getText(), tfPassword.getText());
        }
      } else
        if (dialogButton.equals(btRegister)) {
          Integer temp = register.addUsers(username, password);
          if (temp.equals(-1)) {//用户名已存在
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle(null);
            alert.setHeaderText(null);
            alert.setContentText("用户已存在!");
            alert.showAndWait();
          } else
            if (temp.equals(0)) {//添加失败
              Alert alert = new Alert(Alert.AlertType.WARNING);
              alert.setTitle(null);
              alert.setHeaderText(null);
              alert.setContentText("注册失败!");
              alert.showAndWait();
            } else {
              Alert alert = new Alert(Alert.AlertType.INFORMATION);
              alert.setTitle(null);
              alert.setHeaderText(null);
              alert.setContentText("注册成功!");
              alert.showAndWait();
//              System.out.println("用户注册成功");
            }
        }
      return null;
    });

//    Optional<Pair<String, String>> result = dialog.showAndWait();//可避免空指针
//    result.ifPresent(usernamePassword -> {
//      System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
//    });


    //--------事件处理代码部分------------------
    //  按钮发送按钮
    btnSend.setOnAction(event -> {
      String chatTo = tfChatMember.getText().trim();
      String sendMsg = tfSend.getText();
      if (chatTo.equals("") || chatTo.equals("默认群聊") || chatTo.isEmpty()) {
        chatClient.send(sendMsg);//向服务器发送一串字符
        //主程序不用接收信息，线程接收。否则主程序有可能未能接收消息而卡死。
      } else {
        chatClient.send(chatTo + "&&" + sendMsg);
      }
      tfSend.clear();
    });

    //发送的键盘事件
    tfSend.setOnKeyPressed(event -> {
      String chatTo = tfChatMember.getText().trim();
      String msg = tfSend.getText();
      if (chatTo.equals("") || chatTo.equals("默认群聊") || chatTo.isEmpty()) {
        if (msg.isEmpty()) {
          event.consume();//输入空白则不发送
        }
        if (event.isShiftDown() && event.getCode() == KeyCode.ENTER) {
          chatClient.send(msg);
          taDisplay.appendText("echo:" + msg + "\n");
          tfSend.clear();
        } else
          if (event.getCode() == KeyCode.ENTER) {
            chatClient.send(msg);
            tfSend.clear();
          }
        //主程序不用接收信息，线程接收。否则主程序有可能未能接收消息而卡死。
      } else {
        if (msg.isEmpty()) {
          event.consume();//输入空白则不发送
        }
        if (event.isShiftDown() && event.getCode() == KeyCode.ENTER) {
          chatClient.send(chatTo + "&&" + msg);
          taDisplay.appendText("echo:" + msg + "\n");
          tfSend.clear();
        } else
          if (event.getCode() == KeyCode.ENTER) {
            chatClient.send(chatTo + "&&" + msg);
            tfSend.clear();
          }
      }

    });

    //退出按钮
    btnExit.setOnAction(event -> {
      exit();
    });

    //连接
    btnConnect.setOnAction(event -> {
      try {
        Optional<Pair<String, String>> result = dialog.showAndWait();//可避免空指针
        AtomicReference<String> name = new AtomicReference<>();
        while (!result.isPresent()) {
          Alert alert = new Alert(Alert.AlertType.WARNING);
          alert.setTitle(null);
          alert.setHeaderText(null);
          alert.setContentText("您还未登录，无法进入聊天室！");
          alert.showAndWait();
          result = dialog.showAndWait();
        }
        result.ifPresent(usernamePassword -> {
          name.set(usernamePassword.getKey());
          System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
        });

        chatClient = new ChatClient(ip, port);//成功连接服务器，用线程接受服务器发来的信息
        chatClient.send(name.get());
        tfChatMember.setEditable(true);
        tfSend.setEditable(true);
        btnSend.setDisable(false);
        btnConnect.setDisable(true);
        receiveThread = new Thread(() -> {
          String msg = null;
          while ((msg = chatClient.receive()) != null) {
            final String msgTemp = msg;
            Platform.runLater(() -> {
              taDisplay.appendText(msgTemp + "\n");
            });
          }//跳出了循环，说明服务器已关闭，读取为null，提示对话关闭
          Platform.runLater(() -> {
            taDisplay.appendText("对话已关闭！\n");
          });
        }, "my-readServerThread"); //给新线程取别名，方便识别
        receiveThread.start(); //启动线程


      } catch (Exception e) {
        taDisplay.appendText("服务器连接失败！" + e.getMessage() + "\n");
      }
    });


//在窗体关闭响应的事件中也执行关闭
    primaryStage.setOnCloseRequest(event -> {
      exit();
    });


  }//start—_end

  private void exit() {//“退出”按钮和关闭窗体的事件响应都需要调用这部分代码，所以将之封装为exit()方法
    try {
      if (chatClient != null) {
        chatClient.send("bye"); //向服务器发送关闭连接的约定信息
        Thread.sleep(100);
        chatClient.close();
      }
      System.exit(0);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

}
